package srv

import (
	"context"
	"net/http"
	"time"

	"gogs.xiaoyuanjijiehao.com/antlinker/antcms/app/ginsrv"
	"gogs.xiaoyuanjijiehao.com/antlinker/antcms/app/ginsrv/valid"
	"gogs.xiaoyuanjijiehao.com/antlinker/antcms/ddd"

	"github.com/gin-gonic/gin"
	ut "github.com/go-playground/universal-translator"
	"gogs.xiaoyuanjijiehao.com/antlinker/antcms/log"
)

var (
	_ ginsrv.Server = &server{}
)

// Option 配置参数
type Option struct {
	HTTPAddr          string     `json:"http_addr,omitempty" yaml:"http_addr,omitempty"`                     // 服务监听ip:port
	ReadHeaderTimeout int64      `json:"read_header_timeout,omitempty" yaml:"read_header_timeout,omitempty"` // 读取头信息超时时间单位毫秒
	ReadTimeout       int64      `json:"read_timeout,omitempty" yaml:"read_timeout,omitempty"`               // 读取数据超时时间单位毫秒
	Domain            ddd.Domain `json:"-,omitempty" yaml:"-"`                                               // 领域服务配置
	Debug             bool       `json:"debug,omitempty" yaml:"debug,omitempty"`                             // 是否启用debug模式
	Statics           []Static   `json:"statics,omitempty" yaml:"statics,omitempty"`                         // 代理静态路径
	Cors              Cors       `json:"cors,omitempty" yaml:"cors,omitempty"`                               // 跨域请求
}

// Static 代理静态路径
type Static struct {
	URL  string `json:"url,omitempty" yaml:"url,omitempty"`
	Path string `json:"path,omitempty" yaml:"path,omitempty"`
}

// 解析配置文件，为配置未设置的值填充默认值
func (o Option) parse() Option {
	if o.HTTPAddr == "" {
		o.HTTPAddr = defaultHTTPAddr
	}
	if o.ReadHeaderTimeout <= 0 {
		o.ReadHeaderTimeout = defaultReadHeaderTimeout
	}
	if o.ReadTimeout <= 0 {
		o.ReadTimeout = defaultReadTimeout
	}
	if o.Domain == nil {
		panic("未设置领域服务")
	}
	return o
}

// CreateServer 创建一个服务
func CreateServer(o Option) ginsrv.Server {
	o = o.parse()

	router := gin.New()

	return &server{
		engine: router,
		hsrv: &http.Server{
			Addr:              o.HTTPAddr,
			ReadHeaderTimeout: time.Duration(o.ReadHeaderTimeout) * time.Millisecond,
			ReadTimeout:       time.Duration(o.ReadTimeout) * time.Millisecond,
			Handler:           router,
		},
		opt:    o,
		domain: o.Domain,
	}
}

type server struct {
	hsrv           *http.Server
	engine         *gin.Engine
	handlers       []ginsrv.StartGinHanler
	domain         ddd.Domain
	opt            Option
	validatorTrans ut.Translator
}

func (s *server) RegStartHook(handler ginsrv.StartGinHanler) {
	s.handlers = append(s.handlers, handler)
}
func (s *server) Run() (err error) {
	s.engine.Use(gin.Recovery())

	if gin.Mode() == gin.DebugMode {
		s.opt.Cors.HostRegex = "*"

		s.engine.Use(log.DebugLogger())
	} else {
		s.engine.Use(log.ProdLogger())
	}
	s.engine.Use(valid.Translator())
	s.engine.Use(CorsAllow(s.opt.Cors))
	for _, ss := range s.opt.Statics {
		s.engine.Static(ss.URL, ss.Path)
	}

	if len(s.handlers) > 0 {
		for _, v := range s.handlers {
			v(s.engine)
		}
	}
	// 发出ddd领域驱动模型准备成功事件
	ddd.StartOK()
	// service connections

	log.Infof("启动GIN HTTP 服务:%v", s.opt.HTTPAddr)
	if err = s.hsrv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
		log.Errorf("listen: %s", err)
	} else {
		log.Errorf("close error: %s", err)
		err = nil
	}
	return
}

func (s *server) Shutdown() {
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()
	if err := s.hsrv.Shutdown(ctx); err != nil {
		log.Fatal("Server Shutdown:", err)
	}
}
func (s *server) Domain() ddd.Domain {
	return s.domain
}
func (s *server) Engine() *gin.Engine {
	return s.engine
}
